import { ethers } from 'ethers'
import contractABI from './myABI/contractABI'
import liquidityCertificateABI from './myABI/liquidityCertificateABI'
import usdtABI from './myABI/usdtABI'
import axios from 'axios'
import globalsViewerABI from './myABI/globalsViewerABI'
import epochManageABI from './myABI/epochManageABI'
import {
  MetaDefenderAddress,
  usdtAddress,
  globalsViewerAddress,
  poolLiquidityCertificateAddress,
  epochManageAddress,
} from './contactAddress'

axios.defaults.baseURL =
  'https://api.thegraph.com/subgraphs/name/lutianzhou001/md-mumbai'

var usdtInstance
var provider
var signer
var liquidityCertificateInstance
var globalsViewerInstance

let web3Utils = {
  state() {
    return {
      currentAddress: 'Connect Wallet',
      currentAddressComp: '',
      ethereum: window.ethereum,
      a: 0,
      b: 0,
      protectionOriginShow: true,
      poolLiquidityCertificateArr: {
        [MetaDefenderAddress.toLowerCase()]: poolLiquidityCertificateAddress,
      },
      totalCoverage: 0,
      totalPendingCertificateLiquidity: 0,
      totalPendingCoverage: 0,
      totalValidCertificateLiquidity: 0,
    }
  },
  mutations: {
    changeCurrentAddress(state, address) {
      let disLength = address.length
      state.currentAddressComp = address
      state.currentAddress =
        address.substring(0, 4) +
        '***' +
        address.substring(disLength - 2, disLength)
    },

    protectionOriginHide(state) {
      state.protectionOriginShow = false
    },

    protectionOriginShowAgain(state) {
      state.protectionOriginShow = true
    },

    getDashboardData(
      state,
      {
        totalCoverage,
        totalPendingCertificateLiquidity,
        totalPendingCoverage,
        totalValidCertificateLiquidity,
      }
    ) {
      state.totalCoverage = totalCoverage
      state.totalPendingCertificateLiquidity = totalPendingCertificateLiquidity
      state.totalPendingCoverage = totalPendingCoverage
      state.totalValidCertificateLiquidity = totalValidCertificateLiquidity
    },
  },
  actions: {
    protectionOriginHideDo(context) {
      context.commit('protectionOriginHide')
    },

    protectionOriginShowAgainDo(context) {
      context.commit('protectionOriginShowAgain')
    },

    async getWeb3(context) {
      if (window.ethereum) {
        provider = new ethers.providers.Web3Provider(window.ethereum)
      } else if (window.web3) {
        provider = window.web3.currentProvider
      } else {
        provider = new ethers.providers.JsonRpcProvider(
          //"https://polygon-mainnet.infura.io/v3/295cce92179b4be498665b1b16dfee34"
          //"http://localhost:8545"
          'https://matic-mumbai.chainstacklabs.com'
        )
      }

      signer = provider.getSigner()

      console.log('signer', signer)

      signer.getAddress().then(
        (address) => {
          context.commit('changeCurrentAddress', address)
        },
        (error) => {
          console.log(error)
        }
      )

      //唯一的全局变量是usdt
      usdtInstance = new ethers.Contract(usdtAddress, usdtABI, signer)
      console.log(usdtInstance)

      globalsViewerInstance = new ethers.Contract(
        globalsViewerAddress,
        globalsViewerABI,
        provider
      )
      console.log(globalsViewerInstance)

      let tx = await globalsViewerInstance.getGlobals()
      context.dispatch('web3Data/doupdateGlobalViewerData', tx, { root: true })
      let totalCoverage =
        tx[tx.length - 1]['totalCoverage'].toString() / 10 ** 18
      let totalPendingCertificateLiquidity =
        tx[tx.length - 1]['totalPendingCertificateLiquidity'].toString() /
        10 ** 18
      let totalPendingCoverage =
        tx[tx.length - 1]['totalPendingCoverage'].toString() / 10 ** 18
      let totalValidCertificateLiquidity =
        tx[tx.length - 1]['totalValidCertificateLiquidity'].toString() /
        10 ** 18

      context.commit('getDashboardData', {
        totalCoverage,
        totalPendingCertificateLiquidity,
        totalPendingCoverage,
        totalValidCertificateLiquidity,
      })
      console.log(
        'totalValidCertificateLiquidity',
        totalValidCertificateLiquidity
      )
    },

    async linkWallet() {
      try {
        await provider.send('eth_requestAccounts', [])
        // dispatch('getWeb3')
      } catch (e) {
        console.log('no metamask or already linked')
      }
    },

    async getPolicyNfts(context) {
      signer.getAddress().then(
        (address) => {
          let addressForSearch = address.toLowerCase()
          axios({
            method: 'post',
            url: '',
            data: {
              query: `
                            query {
                                policies(where: {beneficiary: "${addressForSearch}"}) {
                                  SPS
                                  coverage
                                  duration
                                  enteredEpochIndex
                                  fee
                                  id
                                  isClaimApplying
                                  isClaimed
                                  isSettled
                                  standardRisk
                                  policyId
                                  beneficiary
                                  protocol
                                }
                              }

                            `,
            },
          }).then(
            (response) => {
              console.log(response.data.data.policies)
              context.dispatch(
                'web3Data/doupdatePolicyArr',
                response.data.data.policies,
                { root: true }
              )
            },
            (error) => {
              console.log(error)
            }
          )
        },
        (error) => {
          console.log(error)
        }
      )
    },

    async getCertificateNfts(context) {
      signer.getAddress().then(
        (address) => {
          let addressForSearch = address.toLowerCase()
          axios({
            method: 'post',
            url: '',
            data: {
              query: `
                            query {
                              liquidityCertificates (where:  { isValid: true owner : "${addressForSearch}"}) {
                              id
                              certificateId
                              enteredEpochIndex
                              exitedEpochIndex
                              isValid
                              liquidity
                              owner
                              rewardDebtEpochIndex
                              SPSLocked
                              protocol
                              }
                            } 
                            `,
            },
          }).then(
            (response) => {
              context.dispatch(
                'web3Data/doupdateCertificateArr',
                response.data.data.liquidityCertificates,
                { root: true }
              )
            },
            (error) => {
              console.log(error)
            }
          )
        },
        (error) => {
          console.log(error)
        }
      )
    },

    async getMedalNfts(context) {
      signer.getAddress().then(
        (address) => {
          let addressForSearch = address.toLowerCase()
          axios({
            method: 'post',
            url: '',
            data: {
              query: `
                            query {
                              liquidityCertificates (
                                where:  { isValid: false owner : "${addressForSearch}"}
                                
                                ) {
                              id
                              certificateId{
                                orderBy: certificateId
                                  orderDirection: asc
                              }
                              enteredEpochIndex
                              exitedEpochIndex
                              isValid
                              liquidity
                              owner
                              rewardDebtEpochIndex
                              SPSLocked
                              protocol
                              }
                            } 
                            `,
            },
          }).then(
            (response) => {
              console.log(
                'medals===>',
                response.data.data.liquidityCertificates
              )
              context.dispatch(
                'web3Data/doupdateMedalArr',
                response.data.data.liquidityCertificates,
                { root: true }
              )
            },
            (error) => {
              console.log(error)
            }
          )
        },
        (error) => {
          console.log(error)
        }
      )
    },

    async getRewards(context, { certificateId, poolAddress }) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let res = await poolContractInstance.getRewards(certificateId)
        let result = parseInt(res.toHexString(), 16)
        context.dispatch(
          'web3Data/doupdateReward',
          (result / 10 ** 18).toFixed(4),
          { root: true }
        )
      } catch (err) {
        let result = 'Error'
        context.dispatch('web3Data/doupdateReward', result, { root: true })
      }
    },

    async getAllowance(context, { owner, spender }) {
      let allowance = await usdtInstance.allowance(owner, spender)
      return allowance
    },

    // async getApproval(context, { owner, operator }) {
    //     let approval = await liquidityCertificateInstance.isApprovedForAll(owner, operator);
    //     return approval;
    // },

    async approveUsdtForMetaDefender(context, { spender }) {
      try {
        let tx = await usdtInstance.approve(
          spender,
          '10000000000000000000000000'
        )
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    // async approveLiquidityCertificateForMetaDefender(context, { spender }) {
    //     try {
    //         let tx = await liquidityCertificateInstance.setApprovalForAll(spender, true);
    //         let result = await tx.wait();
    //         console.log(result);
    //     } catch (err) {
    //         console.log(err);
    //     }
    // },

    async takeRewards(context, { poolAddress, certificateId }) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let certificateIdInt = parseInt(certificateId)
        let tx = await poolContractInstance.claimRewards(certificateIdInt)
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    async removeLiquidity(context, { poolAddress, certificateId }) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let certificateIdInt = parseInt(certificateId)
        console.log(typeof certificateIdInt)
        let tx = await poolContractInstance.certificateProviderExit(
          certificateIdInt,
          {
            gasPrice: ethers.utils.parseUnits('100', 'gwei'),
            gasLimit: 1000000,
          }
        )
        // let tx = await poolContractInstance["certificateProviderExit(uint256)"](certificateIdInt);
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    async settlePolicy(context, { poolAddress, policyId }) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let policyIdInt = parseInt(policyId)
        console.log(
          policyIdInt,
          poolAddress,
          typeof policyIdInt,
          typeof poolAddress
        )
        let tx = await poolContractInstance.settlePolicy(policyIdInt, {
          gasPrice: ethers.utils.parseUnits('100', 'gwei'),
          gasLimit: 1000000,
        })
        let result = await tx.wait()
        return result
      } catch (err) {
        console.log(typeof err)
        return 'Settling policy failed'
      }
    },

    async applyForClaim(context, { poolAddress, policyId }) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let policyIdInt = parseInt(policyId)
        console.log(policyIdInt)
        let tx = await poolContractInstance.policyClaimApply(policyIdInt)
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    async transferCertificate(
      context,
      { poolAddress, from, to, certificateId }
    ) {
      try {
        let liquidityCertificateAddress =
          context.state.poolLiquidityCertificateArr[poolAddress]
        liquidityCertificateInstance = new ethers.Contract(
          liquidityCertificateAddress,
          liquidityCertificateABI,
          signer
        )
        let certificateIdInt = parseInt(certificateId)
        let tx = await liquidityCertificateInstance[
          'safeTransferFrom(address,address,uint256)'
        ](from, to, certificateIdInt)
        // let tx = await liquidityCertificateInstance.safeTransferFrom(from, to, certificateIdInt);
        console.log(tx)
        let result = await tx.wait()
        console.log(result)
        return result
      } catch (err) {
        console.log(err)
        return 'Transferring certificate failed'
      }
    },

    async buyCover(
      context,
      { poolAddress, coverage, coverPeriod, policyHolder }
    ) {
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let coverageBN = coverage.toString() + '000000000000000000'
        let tx = await poolContractInstance.buyPolicy(
          policyHolder,
          coverageBN,
          coverPeriod
        )
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    async underwrite(context, { poolAddress, amount }) {
      console.log(amount + 'aaa')
      try {
        let poolContractInstance = new ethers.Contract(
          poolAddress,
          contractABI,
          signer
        )
        let amountBN = amount.toString() + '000000000000000000'
        let tx = await poolContractInstance.certificateProviderEntrance(
          amountBN
        )
        let result = await tx.wait()
        console.log(result)
      } catch (err) {
        console.log(err)
      }
    },

    async getTimestampFromEpoch(context, { index }) {
      try {
        let epochManageContractInstance = new ethers.Contract(
          epochManageAddress,
          epochManageABI,
          signer
        )
        let res = await epochManageContractInstance.getTimestampFromEpoch(index)
        context.dispatch('web3Data/doupdateEpochTime', res, { root: true })
      } catch (err) {
        console.log(err)
      }
    },

    async getPremiumRate(context, { amount, date, contract }) {
      console.log('amount', amount)
      console.log('date', date)
      try {
        let res = await globalsViewerInstance.getPremium(amount, date, contract)
        return (parseInt(res.premium.toHexString(), 16) / 10 ** 16).toFixed(4)
      } catch (err) {
        return '-'
      }
    },

    async getWithdrawableAmount(context, { certificateId }) {
      try {
        let withdrawContractInstance = new ethers.Contract(
          MetaDefenderAddress,
          contractABI,
          signer
        )
        let res = await withdrawContractInstance.getSPSLockedByCertificateId(
          certificateId
        )
        context.dispatch(
          'web3Data/doupdateWithdrawableAmount',
          (parseInt(res[1].toHexString(), 16) / 10 ** 18).toFixed(2),
          { root: true }
        )
      } catch (err) {
        let result = 'Error'
        context.dispatch('web3Data/doupdateWithdrawableAmount', result, {
          root: true,
        })
      }
    },
  },
}

export default web3Utils
